﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace Sys.Core
{
    /// <summary>
    /// Sort基类
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    /// <typeparam name="B">实体操作实例类型</typeparam>
    public class ExampleSort<T, B> : ExampleBase<T, B>
        where T : class, new()
        where B : new()
    {
        /// <summary>
        /// 获取排序最大值
        /// </summary>
        /// <param name="sortname">排序字段名称</param>
        /// <returns>最大值+1</returns>
        public virtual int MaxSort(Expression<Func<T, int?>> sortname)
        {
            object max = Entities.Max(sortname);

            if (max != null)
            {
                return Convert.ToInt32(max) + 1;
            }
            else { return 1; }
        }

        /// <summary>
        /// 在指定集合内获取排序最大值
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="sortname">排序字段名称</param>
        /// <returns>最大值+1</returns>
        public virtual int MaxSort(IQueryable<T> entities, Expression<Func<T, int?>> sortname)
        {
            object max = entities.Max(sortname);

            if (max != null)
            {
                return Convert.ToInt32(max) + 1;
            }
            else { return 1; }
        }

        /// <summary>
        /// 获取排序实体列表
        /// </summary>
        /// <param name="model">基础实体</param>
        /// <param name="entities">查询数据对象</param>
        /// <param name="sortname">排序字段</param>
        /// <param name="sortorder">排序方式</param>
        /// <returns>查询结果</returns>
        public virtual IQueryable<T> EntitiesOrder(T model, IQueryable<T> entities, string sortname, string sortorder)
        {
            PropertyInfo property = typeof(T).GetProperty(sortname);
            ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
            MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property);
            LambdaExpression orderByExp = Expression.Lambda(propertyAccess, parameter);

            int temp = Convert.ToInt32(property.GetValue(model, null));
            ConstantExpression sort = Expression.Constant(temp, typeof(int));

            if (sortorder.Equals("up"))
            {
                BinaryExpression lessThan = Expression.LessThan(propertyAccess, sort);
                Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(lessThan, parameter);

                entities = entities.Where(lambda);
                sortorder = "OrderByDescending";
            }
            else
            {
                BinaryExpression greaterThan = Expression.GreaterThan(propertyAccess, sort);
                Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(greaterThan, parameter);

                entities = entities.Where(lambda);
                sortorder = "OrderBy";
            }

            MethodCallExpression resultExp = Expression.Call(typeof(Queryable), sortorder, new Type[] { typeof(T), property.PropertyType }, entities.Expression, Expression.Quote(orderByExp));

            return entities.Provider.CreateQuery<T>(resultExp);
        }

        /// <summary>
        /// 公共排序调整
        /// </summary>
        /// <param name="entities">查询数据对象</param>
        /// <param name="id">实体主键</param>
        /// <param name="sortname">排序字段</param>
        /// <param name="sortorder">排序方式</param>
        /// <param name="success">是否成功</param>
        /// <returns>结果信息</returns>
        public virtual string SetOrder(IQueryable<T> entities, string id, string sortname, string sortorder, out bool success)
        {
            T model = GetByKey(id);

            PropertyInfo property = typeof(T).GetProperty(sortname);

            entities = EntitiesOrder(model, entities, sortname, sortorder);

            var list = EntitiesPage(entities, 1, 1).ToList();

            success = false;

            if (list.Count > 0)
            {
                int temp = Convert.ToInt32(property.GetValue(model, null));
                property.SetValue(model, property.GetValue(list[0], null), null);
                property.SetValue(list[0], temp, null);

                list.Add(model);

                success = Update(list) == 2;

                if (success)
                {
                    return "调整成功!";
                }
                else { return "调整失败!"; }
            }
            else { return "到头啦!"; }
        }
    }
}
